본문으로 이동
메뉴 여닫기
환경 설정 메뉴 여닫기
개인 메뉴 여닫기
로그인하지 않음
지금 편집한다면 당신의 IP 주소가 공개될 수 있습니다.
Variable Transformation; 변수 변환
변수의 척도·분포·형태를 분석 모형에 맞게 바꾸는 전처리 기법

변수마다 단위가 다르면 거리 기반 모형(K-NN, K-평균, SVM)이 큰 값을 가진 변수에 끌려가고, 한쪽으로 치우친 분포는 선형 모형의 가정을 깨뜨린다. 변수 변환은 이런 문제를 줄인다.

기법 공식 결과 특징
표준화(Z-score) z=x−x¯s 평균 0, 표준편차 1 이상값의 영향을 받는다
최소-최대 정규화 x′=x−xminxmax−xmin 0~1 범위 이상값 하나가 범위를 크게 바꾼다
로버스트 스케일링 x′=x−Q2Q3−Q1 중앙값 0 중앙값과 IQR을 써서 이상값에 강하다

오른쪽 꼬리가 긴(양의 왜도) 분포를 정규분포에 가깝게 만든다.

  • 로그 변환 : log⁡x. 0이 있으면 log⁡(x+1)을 쓴다. 소득, 거래 금액처럼 크기 차이가 큰 변수에 쓴다
  • 제곱근 변환 : x. 로그보다 약하게 작용하며 개수(count) 데이터에 쓴다
  • Box-Cox 변환 : 모수 λ를 데이터로 추정하는 거듭제곱 변환. 양수 데이터에만 쓸 수 있다
y(λ)={xλ−1λ(λ≠0)log⁡x(λ=0)
  • Yeo-Johnson 변환 : Box-Cox를 0과 음수까지 쓸 수 있게 확장한 변환

연속형 변수를 몇 개의 구간(범주)으로 나눈다(binning, 이산화).

  • 등간격 구간화 : 구간 폭을 같게 나눈다. pandas cut
  • 등빈도 구간화 : 구간마다 관측 수를 같게 나눈다. pandas qcut
  • 잡음을 줄이는 평활화 효과가 있지만, 정보 손실이 생긴다

변환 방향 정리

편집 원본 편집
상황 변환 효과
오른쪽 꼬리가 긴 분포(양의 왜도) 로그, 제곱근 큰 값을 작게 눌러 꼬리를 줄인다
왼쪽 꼬리가 긴 분포(음의 왜도) 제곱, 지수(exp) 작은 값을 크게 벌려 꼬리를 줄인다
단위·범위가 서로 다름 최소-최대 정규화 값을 0~1 범위로 옮긴다

구간 수와 정확도·속도

편집 원본 편집
  • 구간을 많이 나눌수록 원래 값의 정보가 많이 남아 정확도는 높아질 수 있지만, 범주가 늘어 계산이 느려진다.
  • 구간을 적게 나눌수록 처리는 빨라지지만 정보 손실이 커져 정확도가 떨어진다.
  • "구간 수가 줄면 정확도는 높아지고 속도는 느려진다" 는 두 방향이 모두 거꾸로라 틀리다.

범주형 인코딩

편집 원본 편집
기법 방법 쓰는 곳
원-핫 인코딩 범주마다 0/1 더미 변수를 만든다 순서 없는 명목형 변수. 범주가 많으면 차원이 커진다. 원 핫 인코딩 참고
레이블 인코딩 범주에 정수 0, 1, 2…를 붙인다 트리 모형, 순서형 변수. 선형 모형에서는 가짜 순서가 생긴다

비정형 데이터 변환

편집 원본 편집
  • 텍스트 : 토큰화 후 Bag of Words, TF-IDF, 워드 임베딩 등으로 수치 벡터로 바꾼다
  • 이미지 : 픽셀 값을 0~1로 스케일링하거나 크기를 맞춘 뒤 텐서로 바꾼다
import numpy as np
import pandas as pd
from sklearn.preprocessing import StandardScaler, MinMaxScaler, RobustScaler, PowerTransformer

df = pd.DataFrame({"income": [200, 250, 300, 320, 5000],
                   "city": ["서울", "부산", "서울", "대구", "부산"]})

df["income_std"] = StandardScaler().fit_transform(df[["income"]]).ravel()
df["income_mm"] = MinMaxScaler().fit_transform(df[["income"]]).ravel()
df["income_rb"] = RobustScaler().fit_transform(df[["income"]]).ravel()
df["income_log"] = np.log1p(df["income"])
df["income_bc"] = PowerTransformer(method="box-cox").fit_transform(df[["income"]]).ravel()
df["income_bin"] = pd.qcut(df["income"], q=2, labels=["하", "상"])

df = pd.get_dummies(df, columns=["city"])   # 원-핫 인코딩

스케일러는 학습 데이터로만 fit하고, 같은 객체로 평가 데이터를 transform해야 한다. 평가 데이터까지 합쳐 fit하면 정보가 새어 나간다.

  • 표준화·최소-최대 정규화 값 계산, 이상값에 강한 기법(로버스트 스케일링) 고르기
  • Box-Cox는 양수만 가능하다는 점, 로그 변환이 왜도를 줄인다는 점
  • 원-핫과 레이블 인코딩의 차이, 실기 작업형 2유형에서 인코딩·스케일링 적용